﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

// 文件操作

// 我们为什么要使用文件呢？

// 1.可以长久的存储我们的数据，没有文件存储我们输入的程序代码数据是在电脑
//	 内存中存储的，但是程序结束后，我们的数据也会清空，无法持久化保存

//如以下代码
#if 0
int main()
{
	int a = 0; //创建变量a
	scanf("%d", &a); // 向a中输入数值
	return 0;
}
#endif
// 我们可以通过内存窗口看见int变量a中存放我们输入的值，但是程序结束，数据会清空，我们需要重新输入


// 那么什么是文件呢？

// 文件指的就是磁盘上的文件
// 但是程序中我们的文件分为两种:程序文件，数据文件 - 按照功能划分

// 首先来了解程序文件
// struct 程序文件
//{
//	1.源程序文件(后缀为.c);
//  2.目标文件(windows环境后缀为.obj);
//  3.可执行文件(windows环境后缀为.exe);
//}；

// 其次是数据文件
// 该文件的内容不一定是程序，也可以是运行时读写的数据，比如程序运⾏需要从中读取数据的⽂件，
// 或者输出内容的文件。


// 文件名字
// 用于用户识别和使用，是文件的标识
// 这个相信大家都不陌生，我们在打开磁盘可以在上方的小方块看到当期文件的名字。

// 二进制文件和文本文件

//根据数据不同形式，我们将数据文件划分为二进制文件和文本文件

//二进制文件：以二进制的形式存储，不用转换直接可以输出到外存

//文本文件：字符一律以ASCLL码值存储，需要转换才可以输出到外存


// 文件的打开和关闭

// 在了解文件之前，我们需要认识一种抽象的概念 - 流
// 什么是流呢？我们在生活中获取消息是从人流，网上等等渠道，同理计算机也是如此，
// 我们把从键盘输入，文件读写和其他所有外部的数据糅合起来比作一条流淌着字符的数据河，
// 而计算机则是从河中获取所需要的数据，读取它们，然后打开，再操作数据

// 那么我们有可能有疑问了？我们平时键盘输入代码，屏幕打印字符数据好像并没有使用流啊
// 这里我们就需要引入一个概念 - 标准流
// 标准流在计算机C程序运行启动时就默认打开了3个流：

// 1.stdin  - 标准输入流，获取我们输入的信息。
// 2.stdout - 标准输出流，输出我们需要打印的信息。
// 3.stderr - 标准错误流。

// 有了以上默认打开的流，我们使用scanf和printf就可以进行输入输出操作

// stdin，stdout，stderr 类型为 FILE* - 文件指针
// C语⾔中，就是通过FILE*的⽂件指针来维护流的各种操作的。

// 文件指针

// 我们在打开使用文件时，内存中会开辟一个文件信息区，这个信息区用来存放文件的相关
// 信息，这些信息是保存在一个结构体变量中，取名为FILE。

// 如vs2013编译环境中#include <stdio.h> 头文件种的类型申明。
#if 0
struct _iobuf {
	char* _ptr;
	int _cnt;
	char* _base;
	int _flag;
	int _file;
	int _charbuf;
	int _bufsiz;
	char* _tmpfname;
};
typedef struct _iobuf FILE;
#endif

// 借助这点我们可以定义一个指针变量指向该文件信息区，间接的找到该文件

// FILE* pf; //文件指针变量


// 文件的打开和关闭

// 在读写编辑文件之前，我们需要学会如何打开和关闭文件

// 1.打开文件

// 在编写程序时在打开⽂件的同时，都会返回⼀个FILE*的指针变量指向该⽂件，也相当于建⽴了
// 指针和⽂件的关系。

// ANSIC规定使⽤ fopen 函数来打开⽂件， fclose 来关闭⽂件

// 代码演示：

// 打开文件：
//FILE* fopen(const char* filename, const char* mode);

// 关闭文件：
//int fclose(FILE* stream);

// mode - 文件打开的模式，所有模式如下：

// "r"(只读) - 输入数据，打开一个存在的文本文件 - 如果文件不存在（出错）

// "w"(只写) - 输出数据，打开一个文本文件 - 如果文件不存在（创建一个新的文件）

// "a"(追加) - 向文本文件末尾添加数据 - 如果文件不存在（创建一个新的文件）

// "rb"(只读) - 输入数据，打开一个二进制文本文件 - 如果文件不存在（出错）

// "wb"(只写) - 输出数据，打开一个二进制文本文件 - 如果文件不存在（创建一个新的文件）

// "ab"(追加) - 向二进制文本文件末尾添加数据 - 如果文件不存在（创建一个新的文件）

// "r+"(读写) - 为了读和写，打开一个文本文件 - 如果文件不存在（出错）

// "w+"(读写）- 为了读和写，创建一个文本文件 - 如果文件不存在（创建一个新的文件）

// "a+"(读写）- 打开一个文本文件，在文件末尾进行读写 - 如果文件不存在（创建一个新的文件）

// "rb+"(读写）- 为了读和写，打开一个二进制文本文件 - 如果文件不存在（出错）

// "wb+"(读写）- 为了读和写，创建一个二进制文本文件 - 如果文件不存在（创建一个新的文件）

// "ab+"(读写）- 打开一个二进制文本文件，在文件末尾进行读写 - 如果文件不存在（创建一个新的文件）

#if 0
int main()
{
	// 创建文本指针变量
	FILE* pf;
	//打开文件
	pf = fopen("text.txt", "r");
	//文件操作
	if (pf == NULL)
	{
		//...
		perror("fopen");
		return 1;
	}
	else
	{
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
#endif


// 文件的顺序读写

// 1.顺序读写函数介绍

//  函数    功能          适用于

// fgetc - 字符输入函数 - 所有的输入流

// fputc - 字符输出函数 - 所有的输出流

// fgets - 文本行输入函数 - 所有输入流

// fouts - 文本行输入函数 - 所有输入流

// 